package cn.wygandwdn.core.spring;

import cn.wygandwdn.common.config.RpcServiceConfig;
import cn.wygandwdn.common.factory.SingletonFactory;
import cn.wygandwdn.core.annotation.RpcReference;
import cn.wygandwdn.core.annotation.RpcService;
import cn.wygandwdn.core.registry.PublishService;
import cn.wygandwdn.core.registry.impl.PublishServiceImpl;
import cn.wygandwdn.core.transport.client.RpcClient;
import cn.wygandwdn.core.transport.client.RpcClientProxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;

/**
 * @description:
 * @author: WYG
 * @time: 2021/10/28 20:26
 */
public class SpringBeanPostProcessor implements BeanPostProcessor {

    private static final Logger log = LoggerFactory.getLogger(SpringBeanPostProcessor.class);

    private final PublishService publishService;
    private final RpcClient client;

    public SpringBeanPostProcessor() {
        this.client = SingletonFactory.getInstance(RpcClient.class);
        this.publishService = SingletonFactory.getInstance(PublishServiceImpl.class);
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        log.debug("容器初始化前: {}", beanName);
        if (bean.getClass().isAnnotationPresent(RpcService.class)) {
            log.debug("[{}] is annotated with [{}]", bean.getClass().getName(), RpcService.class.getCanonicalName());
            RpcService annotation = bean.getClass().getAnnotation(RpcService.class);
            String group = annotation.group();
            String version = annotation.version();
            // 获取服务信息并发布
            RpcServiceConfig serviceConfig = new RpcServiceConfig.Builder()
                    .group(group)
                    .version(version)
                    .service(bean)
                    .build();
            log.debug("RpcServiceConfig: {}", serviceConfig);
            publishService.publishService(serviceConfig);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Class<?> aClass = bean.getClass();
        Field[] fields = aClass.getDeclaredFields();
        for (Field field : fields) {
            RpcReference annotation = field.getAnnotation(RpcReference.class);
            if (annotation != null) {
                String group = annotation.group();
                String version = annotation.version();
                RpcClientProxy proxy = new RpcClientProxy(client, group, version);
                Object clientProxy = proxy.getProxy(field.getType());
                field.setAccessible(true);
                try {
                    field.set(bean, clientProxy);
                } catch (IllegalAccessException e) {
                    log.error("proxy error: {}", e);
                }
            }
        }
        return bean;
    }
}
